package com.example.controller;

import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.example.job.MyElasticJob1;
import com.example.job.MyElasticJob2;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.impl.SchedulerRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collection;

@Slf4j
@RestController
@RequestMapping("/api/job")
public class JobController {

    private JobScheduler scheduler1 = null;

    private JobScheduler scheduler2 = null;

    @GetMapping("/initAll")
    public ResponseEntity<String> initAll() {
        try {
            ZookeeperConfiguration zkConfig = new ZookeeperConfiguration("localhost:2181", "elastic-job-demo2");
            ZookeeperRegistryCenter regCenter = new ZookeeperRegistryCenter(zkConfig);
            regCenter.init();

            // 定义作业核心配置
            String cron = "0/1 * * * * ?";
            String shardingItemParameters = "0=A,1=B,2=C";
            JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(MyElasticJob1.class.getName(), cron, 3)
                    .shardingItemParameters(shardingItemParameters)
                    .build();
            // 定义SIMPLE类型配置
            SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MyElasticJob1.class.getCanonicalName());
            // 定义Lite作业根配置
            LiteJobConfiguration jobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();

            // Create job bootstrap
            scheduler1 = new JobScheduler(regCenter, jobConfig);
            scheduler1.init();

            // 定义作业核心配置
            cron = "0/1 * * * * ?";
            shardingItemParameters = "0=A,1=B,2=C";
            simpleCoreConfig = JobCoreConfiguration.newBuilder(MyElasticJob2.class.getName(), cron, 3)
                    .shardingItemParameters(shardingItemParameters)
                    .build();
            // 定义SIMPLE类型配置
            simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MyElasticJob2.class.getCanonicalName());
            // 定义Lite作业根配置
            jobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();
            scheduler2 = new JobScheduler(regCenter, jobConfig);
            scheduler2.init();
            log.info("started");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/shutdown1")
    public ResponseEntity<String> shutdown1() {
        try {
            scheduler1.getSchedulerFacade().shutdownInstance();
            log.info("job1 shutdowned");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/shutdown2")
    public ResponseEntity<String> shutdown2() {
        try {
            scheduler2.getSchedulerFacade().shutdownInstance();
            log.info("job2 shutdowned");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/pauseAll")
    public ResponseEntity<String> pauseAll() {
        try {
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                log.info("job[{}] paused", scheduler.getSchedulerName());
                scheduler.pauseAll();
            }
            log.info("all jobs paused");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/pause1")
    public ResponseEntity<String> pause1() {
        try {
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                if ("com.example.job.MyElasticJob1".equals(scheduler.getSchedulerName())) {
                    log.info("job[{}] paused", scheduler.getSchedulerName());
                    scheduler.pauseAll();
                }
            }
            log.info("all jobs paused");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/pause2")
    public ResponseEntity<String> pause2() {
        try {
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                if ("com.example.job.MyElasticJob2".equals(scheduler.getSchedulerName())) {
                    log.info("job[{}] paused", scheduler.getSchedulerName());
                    scheduler.pauseAll();
                }
            }
            log.info("all jobs paused");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/resumeAll")
    public ResponseEntity<String> resumeAll() {
        try {
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                log.info("job[{}] resumed", scheduler.getSchedulerName());
                scheduler.resumeJob(new JobKey(scheduler.getSchedulerName()));
            }
            log.info("all jobs resumed");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/startAll")
    public ResponseEntity<String> startAll() {
        try {
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                log.info("job[{}] started", scheduler.getSchedulerName());
                scheduler.start();
            }
            log.info("all jobs started");
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/shutDownAll")
    public ResponseEntity<String> shutDownAll() {
        try {
            Collection<Scheduler> schedulers = new ArrayList<>();
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                schedulers.add(scheduler);
            }
            if (CollectionUtils.isNotEmpty(schedulers)) {
                int successCount = 0;
                for (Scheduler scheduler : schedulers) {
                    if (!scheduler.isShutdown()) {
                        try {
                            scheduler.shutdown();
                            ++ successCount;
                            log.info("==>> Job[{}] is shutting down", scheduler.getSchedulerName());
                        } catch (Exception e) {
                            log.error("Job shut down error", e);
                            scheduler.shutdown(); // try again
                        }
                    }
                }
                log.info("==>> Shut down all jobs, totalCount={}, successCount={}", schedulers.size(), successCount);
                schedulers.clear();
            }
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }

    @GetMapping("/restart")
    public ResponseEntity<String> restart() {
        try {
            Collection<Scheduler> schedulers = new ArrayList<>();
            for (Scheduler scheduler : SchedulerRepository.getInstance().lookupAll()) {
                schedulers.add(scheduler);
            }
            if (CollectionUtils.isNotEmpty(schedulers)) {
                int successCount = 0;
                for (Scheduler scheduler : schedulers) {
                    if (!scheduler.isShutdown()) {
                        try {
                            scheduler.shutdown();
                            ++ successCount;
                            log.info("==>> Job[{}] is shutting down", scheduler.getSchedulerName());
                        } catch (Exception e) {
                            log.error("Job shut down error", e);
                            scheduler.shutdown(); // try again
                        }
                    }
                }
                log.info("==>> Shut down all jobs, totalCount={}, successCount={}", schedulers.size(), successCount);
                schedulers.clear();
            }
            return ResponseEntity.ok("");
        } catch (Exception e) {
            log.error("Error in job test", e);
            return ResponseEntity.internalServerError().body("Error: " + e.getMessage());
        }
    }
}
